﻿namespace WebApplication1.Services
{

    using Microsoft.Extensions.Options;
    using MyWatermark;
    using System.Collections.Concurrent;
    using System.IO;
    using WebApplication1.Models;

    public class ImageService
    {
        private readonly StorageSettings _settings;
        private readonly IWebHostEnvironment _env;

        public ImageService(IOptions<StorageSettings> settings, IWebHostEnvironment env)
        {
            _settings = settings.Value;
            _env = env;
        }

        public string GetStoragePath() => Path.Combine(_env.ContentRootPath, _settings.ImagePath);

        public async Task<string> SaveImageAsync(IFormFile file)
        {
            // 验证文件大小
            if (file.Length > _settings.MaxFileSizeMB * 1024 * 1024)
                throw new Exception($"文件大小超过限制 ({_settings.MaxFileSizeMB}MB)");

            // 验证文件扩展名
            var extension = Path.GetExtension(file.FileName).ToLowerInvariant();
            if (!_settings.AllowedExtensions.Contains(extension))
                throw new Exception("不支持的文件类型");

            // 创建存储目录
            var storagePath = GetStoragePath();
            if (!Directory.Exists(storagePath))
                Directory.CreateDirectory(storagePath);

            // 生成安全文件夹名称（基于原始文件名）
            var originalName = Path.GetFileNameWithoutExtension(file.FileName);
            var folderName = GenerateSafeFolderName(originalName);

            // 生成唯一文件夹路径
            var (finalFolderPath, folderId) = GetUniqueFolderPath(storagePath, folderName);

            // 创建目标文件夹
            Directory.CreateDirectory(finalFolderPath);

            // 构建文件保存路径
            var filePath = Path.Combine(finalFolderPath, $"original{extension}");

            // 保存文件（使用FileMode.CreateNew防止覆盖）
            try
            {
                using var stream = new FileStream(filePath, FileMode.CreateNew);
                await file.CopyToAsync(stream);
            }
            catch (IOException) when (File.Exists(filePath))
            {
                throw new Exception("文件已存在，请勿重复上传");
            }

            return folderId; // 返回文件夹标识
        }

        private string GenerateSafeFolderName(string originalName)
        {
            // 1. 移除非法字符
            var invalidChars = Path.GetInvalidFileNameChars();
            var cleanName = new string(originalName
                .Where(c => !invalidChars.Contains(c))
                .ToArray());

            // 2. 替换空格为下划线
            cleanName = cleanName.Replace(" ", "_");

            // 3. 限制最大长度
            const int maxLength = 50;
            if (cleanName.Length > maxLength)
            {
                cleanName = cleanName[..maxLength];
            }

            // 4. 处理空名称
            if (string.IsNullOrWhiteSpace(cleanName))
            {
                return Guid.NewGuid().ToString("N");
            }

            return cleanName;
        }

        private (string folderPath, string folderId) GetUniqueFolderPath(string rootPath, string baseName)
        {
            int counter = 0;
            while (true)
            {
                // 生成候选文件夹名称
                var folderId = counter == 0
                    ? baseName
                    : $"{baseName}_{counter}";

                var fullPath = Path.Combine(rootPath, folderId);

                // 检查文件夹是否存在且是否包含original文件
                if (!Directory.Exists(fullPath) ||
                   !Directory.EnumerateFiles(fullPath, "original.*").Any())
                {
                    return (fullPath, folderId);
                }

                counter++;

                // 安全限制
                if (counter > 1000)
                    throw new Exception("无法生成唯一文件夹，请修改文件名");
            }
        }

        public FileStream? GetImageStream(string folderId)
        {
            var folderPath = Path.Combine(GetStoragePath(), folderId);

            if (!Directory.Exists(folderPath))
                return null;

            // 查找目录中的original文件
            var files = Directory.GetFiles(folderPath, "original.*");
            if (files.Length == 0)
                return null;

            return new FileStream(files[0], FileMode.Open);
        }


        public async Task<(List<FolderInfo> Result, int TotalCount)> GetFoldersPagedAsync(int page, int pageSize)
        {
            return await Task.Run(() =>
            {
                var storagePath = GetStoragePath();

                if (!Directory.Exists(storagePath))
                    return (new List<FolderInfo>(), 0);

                // 获取所有文件夹
                var folders = Directory.GetDirectories(storagePath)
                    .Select(f => new DirectoryInfo(f))
                    .Where(f => !IsSystemFolder(f)) // 过滤系统文件夹
                    .ToList();

                // 分页处理
                var totalCount = folders.Count;
                var pagedFolders = folders
                    .OrderByDescending(f => f.CreationTime)
                    .Skip((page - 1) * pageSize)
                    .Take(pageSize)
                    .ToList();

                // 并行处理文件检查
                var result = new ConcurrentBag<FolderInfo>();
                Parallel.ForEach(pagedFolders, folder =>
                {
                    var files = Directory.GetFiles(folder.FullName);
                    var originalFile = files.FirstOrDefault(f =>
                        Path.GetFileNameWithoutExtension(f).Equals("original", StringComparison.OrdinalIgnoreCase));

                    var watermarkFile = files.FirstOrDefault(f =>
                        Path.GetFileNameWithoutExtension(f).Equals("watermark", StringComparison.OrdinalIgnoreCase));

                    result.Add(new FolderInfo
                    {
                        Name = folder.Name,
                        CreatedTime = folder.CreationTime,
                        HasOriginal = originalFile != null,
                        HasWatermark = watermarkFile != null,
                        FileExtension = originalFile != null ?
                            Path.GetExtension(originalFile).TrimStart('.') : null,
                        TotalFiles = files.Length
                    });
                });

                return (result.ToList(), totalCount);

            });
        }


        private bool IsSystemFolder(DirectoryInfo dir)
        {
            // 过滤隐藏文件夹和系统保留名称
            var attributes = dir.Attributes;
            return attributes.HasFlag(FileAttributes.Hidden) ||
                   dir.Name.StartsWith(".") || // 隐藏文件夹
                   dir.Name.Equals("temp", StringComparison.OrdinalIgnoreCase);
        }


        public async Task<string> MakeWater(string fileName, string watermarkTxt)
        {
            return await Task.Run(() =>
            {
                try
                {
                    var folderPath = Path.Combine(GetStoragePath(), fileName);
                    var files = Directory.GetFiles(folderPath, "original.*");
                    if (files.Length == 0)
                    {
                        return "源文件不存在";
                    }

                    var fileBytes = File.ReadAllBytes(files[0]);
                    var watermark = WatermarkCore.TextToBinaryWithHeader(watermarkTxt);
                    byte[] watermarked = WatermarkCore.Embed(watermark, fileBytes);

                    var targetPath = $@"{folderPath}\watermark.{Path.GetExtension(files[0]).TrimStart('.')}";
                    File.WriteAllBytes(targetPath, watermarked);

                    return "成功";
                }
                catch (Exception ex)
                {
                    return ex.Message;
                }
            });
        }

        public async Task<string> Extract(IFormFile file)
        {
            return await Task.Run(() =>
            {
                try
                {
                    var memoryStream = new MemoryStream();
                    file.CopyTo(memoryStream);
                    return WatermarkCore.BinaryToTextWithHeader(WatermarkCore.Extract(memoryStream.ToArray()));

                }
                catch (Exception ex)
                {
                    return ex.Message;
                }
            });
        }

        public async Task<(byte[]?, DebugInfo info)> UploadAndEmbed(IFormFile file, string watermarkTxt)
        {
            return await Task.Run(() =>
            {
                try
                {
                    var memoryStream = new MemoryStream();
                    file.CopyTo(memoryStream);
                    DebugInfo info = null;
                    return (WatermarkCore.Embed(WatermarkCore.TextToBinaryWithHeader(watermarkTxt), memoryStream.ToArray(), true, out info), info);

                }
                catch (Exception ex)
                {
                    return (null, null);
                }
            });
        }

        public async Task<(byte[]?, DebugInfo info)> EmbedBytes(byte[] data, string watermarkTxt)
        {
            return await Task.Run(() =>
            {
                try
                {
                    DebugInfo info = null;
                    return (WatermarkCore.Embed(WatermarkCore.TextToBinaryWithHeader(watermarkTxt), data, true, out info), info);

                }
                catch (Exception ex)
                {
                    return (null, null);
                }
            });
        }

        public async Task<string> ExtractString(byte[] data)
        {
            return await Task.Run(() =>
            {
                try
                {
                    return WatermarkCore.BinaryToTextWithHeader(WatermarkCore.Extract(data));

                }
                catch (Exception ex)
                {
                    return ex.Message;
                }
            });
        }

    }
}
